package com.cx.mapper.impl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.Table;

import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import com.cx.entity.BaseEntity;
import com.cx.exception.DBException;
import com.cx.mapper.BaseMapper;
import com.cx.utils.page.Page;
import com.cx.utils.rps.RequestParameters;

public class BaseMapperImpl<T extends BaseEntity> extends SqlSessionDaoSupport implements BaseMapper<T>{
	//日志
	private static Logger log = Logger.getLogger(BaseMapperImpl.class);
	//通过实体类注解获取到值
	private String entityName;
	//泛型实体类
	private Class<T> entityClass;
	
	/**
	 * sqlmapper中对应的DML中id
	 */
	private static final String ENTITY_INSERT = "insertEntity";
	
	private static final String ENTITY_DEL = "delEntity";
	
	private static final String ENTITY_UPDATE =  "updateEntity";
	
	private static final String ENTITY_SELECTBYID = "selectById";
	
	private static final String ENTITY_SELECTBYWHERE = "selectByWhere";
	
	private static final String ENTITY_SELECTPAGEBYWHERE = "selectPageByWhere";
	/**
	 * 通过注解映射获取到sqlSession
	 */
	@Resource
	public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
		super.setSqlSessionFactory(sqlSessionFactory);
	}
	
	/**
	 * 通过泛型获取到实体类，然后获取到注解值，映射到sqlMapper的命名空间.
	 * 当有类继承此类时，实例对象会执行此构造方法（getClass则就不是BaseMapperImpl，而是子类）
	 * 可获取到泛型的实体类，实体类注解name
	 */
	@SuppressWarnings("unchecked")
	public BaseMapperImpl() {
		//获取超类(此类中，超类是org.mybatis.spring.support.SqlSessionDaoSupport)
		Type type =  getClass().getGenericSuperclass();
		//ParameterizedType可获取泛型参数
		Type[] types = ((ParameterizedType) type).getActualTypeArguments();
		entityClass =(Class<T>)types[0];
		//获取到table注解
		Table table = entityClass.getAnnotation(Table.class);
		String tableName = null;
		if (table != null) {
			tableName = table.name();
			if (!"".equals(tableName)) {
				entityName = tableName;
			}
		}
	}
	
	/**
	 * 
	 * @Description(功能描述)    :  异常处理
	 * @author(作者)             ：  曹轩
	 * @date (开发日期)          :  2015年9月28日 下午1:44:36 
	 * @exception                : 
	 * @param sqlId
	 * @param e  void
	 */
	public void handleException(String sqlId, Exception e){
		log.error("dao EXCEPTION",e);
		StringBuilder sb = new StringBuilder();
		sb.append("sqlId:").append(sqlId).append("\nException:").append(e.getMessage());
		throw new DBException(sb.toString());
	}
	
	@Override
	public Long insert(T entity) {
		String statementName = entityName + "." + ENTITY_INSERT;
		log.debug("执行insert方法:"+statementName);
		try{
			getSqlSession().insert(statementName, entity);
		}catch(Exception e) {
			handleException(statementName, e);
		}	
		Long uuid = entity.getUuid();
		return uuid;
	}

	@Override
	public void update(T entity) {
		String statementName = entityName + "." +ENTITY_UPDATE;
		log.debug("执行update方法:"+statementName);
		try{
			getSqlSession().update(statementName, entity);
		}catch(Exception e) {
			handleException(statementName, e);
		}	
	}

	@Override
	public T getEntityById(String id) {
		String statementName = entityName + "." + ENTITY_SELECTBYID;
		log.debug("执行getEntityById方法:"+statementName);
		try{
			return getSqlSession().selectOne(statementName, id);
		}catch(Exception e) {
			handleException(statementName, e);
		}	
		return null;
	}

	@Override
	public T getEntityByWhere(RequestParameters rps) {
		String statementName = entityName + "." + ENTITY_SELECTBYWHERE;
		log.debug("执行getEntityByWhere:"+statementName);
		try{
			return getSqlSession().selectOne(statementName, rps);
		}catch(Exception e) {
			handleException(statementName, e);
		}	
		return null;
	}
	
	@Override
	public void deleteById(String id) {
		String statementName = entityName + "." + ENTITY_DEL;
		log.debug("执行deleteById方法:"+statementName);
		try{
			 getSqlSession().delete(statementName, id);
		}catch(Exception e) {
			handleException(statementName, e);
		}	
	}

	@Override
	public List<T> queryListByRps(RequestParameters rps) {
		String statementName = entityName + "." + ENTITY_SELECTBYWHERE;
		log.debug("执行queryListByRps方法:"+statementName);
		try{
			return getSqlSession().selectList(statementName, rps);
		}catch(Exception e) {
			handleException(statementName, e);
		}	
		return null;
	}

	@Override
	public Page<T> queryForPageByRps(RequestParameters rps, int pageNo, int limit) {
		String statementName = entityName + "." + ENTITY_SELECTPAGEBYWHERE;
		return queryPageByRps(statementName,rps,pageNo,limit);
	}

	/**
	 * 
	 * @Description(功能描述)    :  分页查询数据集合
	 * @author(作者)             ：  曹轩
	 * @date (开发日期)          :  2015年9月28日 下午3:49:22 
	 * @exception                : 
	 * @param statementName
	 * @param rps
	 * @param pageNo
	 * @param limit
	 * @return  Page<T>
	 */
	private Page<T> queryPageByRps(String statementName, RequestParameters rps, int pageNo, int limit) {
		Page<T> page = new Page<T>();
		page.setLimit(limit);
		page.setPageNo(pageNo);
		page.setTotal(getResultCount(statementName, rps));
		RowBounds rb = new RowBounds(page.getStartNo(), limit);
		try{
			int startSet = page.getStartNo();
			log.debug("开始条数=" + startSet + ",limit=" + limit);
			List<T> result = getSqlSession().selectList(statementName, rps, rb);
			page.setResultList(result);
		}catch(Exception e) {
			handleException(statementName, e);
		}	
		return page;
	}
	
	/**
	 * 
	 * @Description(功能描述)    :  获取结果总数
	 * @author(作者)             ：  曹轩
	 * @date (开发日期)          :  2015年9月29日 上午11:47:59 
	 * @exception                : 
	 * @param statementName
	 * @param rps
	 * @return  int
	 */
	private int getResultCount(String statementName, RequestParameters rps){
		List<Object> result =  getSqlSession().selectList(statementName, rps);
		return result.size();
	}
}
